﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Reflection.Emit;
using System.IO;
using System.Reflection;
using System.Threading;

namespace Teal.Compiler {

    /// <summary>
    /// 表示一个用于生成代码的上下文对象。
    /// </summary>
    public sealed class EmitContext {

        //public AppDomain currentDomain;

        //public AssemblyBuilder currentAssembly;
        //public System.Reflection.Emit.ModuleBuilder currentModule;

        ///// <summary>
        ///// 当前正在使用的 IL 代码生成器。
        ///// </summary>
        //public ILGenerator currentGenerator;

        ///// <summary>
        ///// 获取当前正在生成的类型。
        ///// </summary>
        //public System.Reflection.Emit.TypeBuilder currentType;

        //public Label loopBegin;
        //public Label loopEnd;
        //public Label? returnLabel;
        //public bool checkOverflow;

        //public EmitContext(string moduleName) {

        //    if (File.Exists(Compiler.outputPath)) {
        //        File.Delete(Compiler.outputPath);
        //    }

        //    currentDomain = AppDomain.CurrentDomain;

        //    currentAssembly = currentDomain.DefineDynamicAssembly(new System.Reflection.AssemblyName(moduleName), System.Reflection.Emit.AssemblyBuilderAccess.Save, Path.GetDirectoryName(Compiler.outputPath));

        //    currentModule = currentAssembly.DefineDynamicModule(moduleName, Path.GetFileName(Compiler.outputPath), Compiler.outputDebug);

        //    currentType = currentModule.DefineType("__TeaGeneratedGlobalClass");
        //}

        //public void setEntryPoint(MethodReference member) {
        //    //_assembly.SetEntryPoint(_assembly.GetType("Program").GetMethod("main"));
        //}

        //public void save() {
        //    currentType.CreateType();

        //    string fileName = Path.GetFileName(Compiler.outputPath);

        //    for (int i = 9; i >= 0; i--) {
        //        try {
        //            currentAssembly.Save(fileName);
        //            break;
        //        } catch (Exception) {
        //            Compiler.warning(1, String.Format("未能创建文件 “{0}”，该文件被其它进程占用。1000 毫秒后将进行第 {1} 次尝试。", Compiler.outputPath, 10 - i));
        //            if (i == 0) {
        //                throw;
        //            }
        //            Thread.Sleep(1000);
        //        }
        //    }

        //}

        //#region ILGenerator

        ////     BUFFER MANAGEMENT
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Emits a return statement and finalizes the generated code.  Do not emit any more
        ///// instructions after calling this method.
        ///// </summary>
        //public void Complete() {
        //    emitReturn();
        //}



        ////     STACK MANAGEMENT
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Pops the value from the top of the stack.
        ///// </summary>
        //public void emitPop() {
        //    currentGenerator.Emit(OpCodes.Pop);
        //}

        ///// <summary>
        ///// Duplicates the value on the top of the stack.
        ///// </summary>
        //public void emitDuplicate() {
        //    currentGenerator.Emit(OpCodes.Dup);
        //}



        ////     BRANCHING AND LABELS
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Creates a label without setting its position.
        ///// </summary>
        ///// <returns> A new label. </returns>
        //public Label createLabel() {
        //    return currentGenerator.DefineLabel();
        //}

        ///// <summary>
        ///// Defines the position of the given label.
        ///// </summary>
        ///// <param name="label"> The label to define. </param>
        //public void markLabel(Label label) {
        //    currentGenerator.MarkLabel(label);
        //}

        //public Label markLabel() {
        //    Label label = createLabel();
        //    markLabel(label);
        //    return label;
        //}

        ///// <summary>
        ///// Unconditionally branches to the given label.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranch(Label label) {
        //    currentGenerator.Emit(OpCodes.Br, label);
        //}

        ///// <summary>
        ///// Unconditionally branches to the given label.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public Label emitBranch() {
        //    Label label = createLabel();
        //    currentGenerator.Emit(OpCodes.Br, label);
        //    return label;
        //}

        ///// <summary>
        ///// Unconditionally branches to the given label.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchShort(Label label) {
        //    currentGenerator.Emit(OpCodes.Br_S, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the value on the top of the stack is zero.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfFalse(Label label) {


        //    currentGenerator.Emit(OpCodes.Brfalse, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the value on the top of the stack is zero.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public Label emitBranchIfFalse() {
        //    var label = createLabel();
        //    currentGenerator.Emit(OpCodes.Brfalse, label);
        //    return label;
        //}

        ///// <summary>
        ///// Branches to the given label if the value on the top of the stack is non-zero, true or
        ///// non-null.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfTrue(Label label) {


        //    currentGenerator.Emit(OpCodes.Brtrue, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the two values on the top of the stack are equal.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfEqual(Label label) {
        //    currentGenerator.Emit(OpCodes.Beq, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the two values on the top of the stack are equal.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfEqualShort(Label label) {
        //    currentGenerator.Emit(OpCodes.Beq_S, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the two values on the top of the stack are not equal.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfNotEqual(Label label) {

        //    currentGenerator.Emit(OpCodes.Bne_Un, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the first value on the stack is greater than the second
        ///// value on the stack.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfGreaterThan(Label label) {


        //    currentGenerator.Emit(OpCodes.Bgt, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the first value on the stack is greater than the second
        ///// value on the stack.  If the operands are integers then they are treated as if they are
        ///// unsigned.  If the operands are floating point numbers then a NaN value will trigger a
        ///// branch.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfGreaterThanUnsigned(Label label) {


        //    currentGenerator.Emit(OpCodes.Bgt_Un, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the first value on the stack is greater than or equal to
        ///// the second value on the stack.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfGreaterThanOrEqual(Label label) {


        //    currentGenerator.Emit(OpCodes.Bge, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the first value on the stack is greater than or equal to
        ///// the second value on the stack.  If the operands are integers then they are treated as
        ///// if they are unsigned.  If the operands are floating point numbers then a NaN value will
        ///// trigger a branch.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfGreaterThanOrEqualUnsigned(Label label) {


        //    currentGenerator.Emit(OpCodes.Bge_Un, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the first value on the stack is less than the second
        ///// value on the stack.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfLessThan(Label label) {


        //    currentGenerator.Emit(OpCodes.Blt, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the first value on the stack is less than the second
        ///// value on the stack.  If the operands are integers then they are treated as if they are
        ///// unsigned.  If the operands are floating point numbers then a NaN value will trigger a
        ///// branch.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfLessThanUnsigned(Label label) {


        //    currentGenerator.Emit(OpCodes.Blt_Un, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the first value on the stack is less than or equal to
        ///// the second value on the stack.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfLessThanOrEqual(Label label) {


        //    currentGenerator.Emit(OpCodes.Ble, label);
        //}

        ///// <summary>
        ///// Branches to the given label if the first value on the stack is less than or equal to
        ///// the second value on the stack.  If the operands are integers then they are treated as
        ///// if they are unsigned.  If the operands are floating point numbers then a NaN value will
        ///// trigger a branch.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitBranchIfLessThanOrEqualUnsigned(Label label) {


        //    currentGenerator.Emit(OpCodes.Ble_Un, label);
        //}

        ///// <summary>
        ///// Returns from the current method.  A value is popped from the stack and used as the
        ///// return value.
        ///// </summary>
        //public void emitReturn() {
        //    currentGenerator.Emit(OpCodes.Ret);
        //}

        ///// <summary>
        ///// Creates a jump table.  A value is popped from the stack - this value indicates the
        ///// index of the label in the <paramref name="labels"/> array to jump to.
        ///// </summary>
        ///// <param name="labels"> A array of labels. </param>
        //public void emitSwitch(Label[] labels) {
        //    currentGenerator.Emit(OpCodes.Switch, labels);
        //}



        ////     LOCAL VARIABLES AND ARGUMENTS
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Declares a new local variable.
        ///// </summary>
        ///// <param name="type"> The type of the local variable. </param>
        ///// <param name="name"> The name of the local variable. Can be <c>null</c>. </param>
        ///// <returns> A new local variable. </returns>
        //public LocalBuilder createVariable(Type type) {
        //    return currentGenerator.DeclareLocal(type);
        //}

        ///// <summary>
        ///// Declares a new local variable.
        ///// </summary>
        ///// <param name="type"> The type of the local variable. </param>
        ///// <param name="name"> The name of the local variable. Can be <c>null</c>. </param>
        ///// <returns> A new local variable. </returns>
        //public LocalBuilder createVariable(Type type, string name) {
        //    LocalBuilder ret = currentGenerator.DeclareLocal(type);
        //    if (Compiler.outputDebug) {
        //        ret.SetLocalSymInfo(name);
        //    }

        //    return ret;
        //}

        ///// <summary>
        ///// Pushes the value of the given variable onto the stack.
        ///// </summary>
        ///// <param name="variable"> The variable whose value will be pushed. </param>
        //public void emitLoadVariable(LocalBuilder variable) {
        //    currentGenerator.Emit(OpCodes.Ldloc, variable);
        //}

        ///// <summary>
        ///// Pushes the address of the given variable onto the stack.
        ///// </summary>
        ///// <param name="variable"> The variable whose address will be pushed. </param>
        //public void loadAddressOfVariable(LocalBuilder variable) {
        //    currentGenerator.Emit(OpCodes.Ldloca, variable);
        //}

        ///// <summary>
        ///// Pops the value from the top of the stack and stores it in the given local variable.
        ///// </summary>
        ///// <param name="variable"> The variable to store the value. </param>
        //public void emitStoreVariable(LocalBuilder variable) {
        //    currentGenerator.Emit(OpCodes.Stloc, variable);
        //}

        ///// <summary>
        ///// Pushes the value of the method argument with the given index onto the stack.
        ///// </summary>
        ///// <param name="argumentIndex"> The index of the argument to push onto the stack. </param>
        //public void emitLoadArgument(int argumentIndex) {
        //    if (argumentIndex < 0)
        //        throw new ArgumentOutOfRangeException("argumentIndex");
        //    switch (argumentIndex) {
        //        case 0:
        //            currentGenerator.Emit(OpCodes.Ldarg_0);
        //            break;
        //        case 1:
        //            currentGenerator.Emit(OpCodes.Ldarg_1);
        //            break;
        //        case 2:
        //            currentGenerator.Emit(OpCodes.Ldarg_2);
        //            break;
        //        case 3:
        //            currentGenerator.Emit(OpCodes.Ldarg_3);
        //            break;
        //        default:
        //            if (argumentIndex < 256)
        //                currentGenerator.Emit(OpCodes.Ldarg_S, (byte)argumentIndex);
        //            else
        //                currentGenerator.Emit(OpCodes.Ldarg, (short)argumentIndex);
        //            break;
        //    }
        //}

        ///// <summary>
        ///// Pops a value from the stack and stores it in the method argument with the given index.
        ///// </summary>
        ///// <param name="argumentIndex"> The index of the argument to store into. </param>
        //public void emitStoreArgument(int argumentIndex) {
        //    if (argumentIndex < 0)
        //        throw new ArgumentOutOfRangeException("argumentIndex");
        //    if (argumentIndex < 256)
        //        currentGenerator.Emit(OpCodes.Starg_S, (byte)argumentIndex);
        //    else
        //        currentGenerator.Emit(OpCodes.Starg, (short)argumentIndex);
        //}



        ////     LOAD CONSTANT
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Pushes <c>null</c> onto the stack.
        ///// </summary>
        //public void loadNull() {
        //    currentGenerator.Emit(OpCodes.Ldnull);
        //}

        ///// <summary>
        ///// Pushes a constant value onto the stack.
        ///// </summary>
        ///// <param name="value"> The integer to push onto the stack. </param>
        //public void emitLoadInt32(int value) {
        //    if (value >= -1 && value <= 8) {
        //        switch (value) {
        //            case -1:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_M1);
        //                break;
        //            case 0:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_0);
        //                break;
        //            case 1:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_1);
        //                break;
        //            case 2:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_2);
        //                break;
        //            case 3:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_3);
        //                break;
        //            case 4:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_4);
        //                break;
        //            case 5:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_5);
        //                break;
        //            case 6:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_6);
        //                break;
        //            case 7:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_7);
        //                break;
        //            case 8:
        //                currentGenerator.Emit(OpCodes.Ldc_I4_8);
        //                break;
        //        }

        //    } else if (value >= -128 && value < 128)
        //        currentGenerator.Emit(OpCodes.Ldc_I4_S, (byte)value);
        //    else
        //        currentGenerator.Emit(OpCodes.Ldc_I4, value);
        //}

        ///// <summary>
        ///// Pushes a 64-bit constant value onto the stack.
        ///// </summary>
        ///// <param name="value"> The 64-bit integer to push onto the stack. </param>
        //public void emitLoadInt64(long value) {
        //    currentGenerator.Emit(OpCodes.Ldc_I8, value);
        //}

        //public void emitLoadTrue() {
        //    currentGenerator.Emit(OpCodes.Ldc_I4_1);
        //}

        //public void emitLoadFalse() {
        //    currentGenerator.Emit(OpCodes.Ldc_I4_0);
        //}

        ///// <summary>
        ///// Pushes a constant value onto the stack.
        ///// </summary>
        ///// <param name="value"> The number to push onto the stack. </param>
        //public void emitLoadDouble(double value) {
        //    currentGenerator.Emit(OpCodes.Ldc_R8, value);
        //}

        ///// <summary>
        ///// Pushes a constant value onto the stack.
        ///// </summary>
        ///// <param name="value"> The string to push onto the stack. </param>
        //public void emitLoadString(string value) {
        //    currentGenerator.Emit(OpCodes.Ldstr, value);
        //}



        ////     RELATIONAL OPERATIONS
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Pops two values from the stack, compares, then pushes <c>1</c> if the first argument
        ///// is equal to the second, or <c>0</c> otherwise.  Produces <c>0</c> if one or both
        ///// of the arguments are <c>NaN</c>.
        ///// </summary>
        //public void emitCompareEqual() {
        //    currentGenerator.Emit(OpCodes.Ceq);
        //}

        ///// <summary>
        ///// Pops two values from the stack, compares, then pushes <c>1</c> if the first argument
        ///// is greater than the second, or <c>0</c> otherwise.  Produces <c>0</c> if one or both
        ///// of the arguments are <c>NaN</c>.
        ///// </summary>
        //public void emitCompareGreaterThan() {
        //    currentGenerator.Emit(OpCodes.Cgt);
        //}

        ///// <summary>
        ///// Pops two values from the stack, compares, then pushes <c>1</c> if the first argument
        ///// is greater than the second, or <c>0</c> otherwise.  Produces <c>1</c> if one or both
        ///// of the arguments are <c>NaN</c>.  Integers are considered to be unsigned.
        ///// </summary>
        //public void emitCompareGreaterThanUnsigned() {
        //    currentGenerator.Emit(OpCodes.Cgt_Un);
        //}

        ///// <summary>
        ///// Pops two values from the stack, compares, then pushes <c>1</c> if the first argument
        ///// is less than the second, or <c>0</c> otherwise.  Produces <c>0</c> if one or both
        ///// of the arguments are <c>NaN</c>.
        ///// </summary>
        //public void emitCompareLessThan() {
        //    currentGenerator.Emit(OpCodes.Clt);
        //}

        ///// <summary>
        ///// Pops two values from the stack, compares, then pushes <c>1</c> if the first argument
        ///// is less than the second, or <c>0</c> otherwise.  Produces <c>1</c> if one or both
        ///// of the arguments are <c>NaN</c>.  Integers are considered to be unsigned.
        ///// </summary>
        //public void emitCompareLessThanUnsigned() {
        //    currentGenerator.Emit(OpCodes.Clt_Un);
        //}



        ////     ARITHMETIC AND BITWISE OPERATIONS
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Pops two values from the stack, adds them together, then pushes the result to the
        ///// stack.
        ///// </summary>
        //public void emitAdd() {
        //    currentGenerator.Emit(OpCodes.Add);
        //}

        ///// <summary>
        ///// Pops two values from the stack, adds them together, then pushes the result to the
        ///// stack.
        ///// </summary>
        //public void emitAddWithCheck(TypeReference targetType) {
        //    currentGenerator.Emit(OpCodes.Add_Ovf);
        //}

        ///// <summary>
        ///// Pops two values from the stack, subtracts the second from the first, then pushes the
        ///// result to the stack.
        ///// </summary>
        //public void emitSubtract() {
        //    currentGenerator.Emit(OpCodes.Sub);
        //}

        ///// <summary>
        ///// Pops two values from the stack, subtracts the second from the first, then pushes the
        ///// result to the stack.
        ///// </summary>
        //public void emitSubtractOverflow() {
        //    currentGenerator.Emit(OpCodes.Sub_Ovf);
        //}

        ///// <summary>
        ///// Pops two values from the stack, multiplies them together, then pushes the
        ///// result to the stack.
        ///// </summary>
        //public void emitMultiply() {
        //    currentGenerator.Emit(OpCodes.Mul);
        //}

        ///// <summary>
        ///// Pops two values from the stack, divides the first by the second, then pushes the
        ///// result to the stack.
        ///// </summary>
        //public void emitDivide() {
        //    currentGenerator.Emit(OpCodes.Div);
        //}

        ///// <summary>
        ///// Pops two values from the stack, divides the first by the second, then pushes the
        ///// remainder to the stack.
        ///// </summary>
        //public void emitRemainder() {
        //    currentGenerator.Emit(OpCodes.Rem);
        //}

        ///// <summary>
        ///// Pops a value from the stack, negates it, then pushes it back onto the stack.
        ///// </summary>
        //public void emitNegate() {
        //    currentGenerator.Emit(OpCodes.Neg);
        //}

        ///// <summary>
        ///// Pops two values from the stack, ANDs them together, then pushes the result to the
        ///// stack.
        ///// </summary>
        //public void emitBitwiseAnd() {
        //    currentGenerator.Emit(OpCodes.And);
        //}

        ///// <summary>
        ///// Pops two values from the stack, ORs them together, then pushes the result to the
        ///// stack.
        ///// </summary>
        //public void emitBitwiseOr() {
        //    currentGenerator.Emit(OpCodes.Or);
        //}

        ///// <summary>
        ///// Pops two values from the stack, XORs them together, then pushes the result to the
        ///// stack.
        ///// </summary>
        //public void BitwiseXor() {
        //    currentGenerator.Emit(OpCodes.Xor);
        //}

        ///// <summary>
        ///// Pops a value from the stack, inverts it, then pushes the result to the stack.
        ///// </summary>
        //public void emitBitwiseNot() {
        //    currentGenerator.Emit(OpCodes.Not);
        //}

        ///// <summary>
        ///// Pops two values from the stack, shifts the first to the left, then pushes the result
        ///// to the stack.
        ///// </summary>
        //public void emitShiftLeft() {
        //    currentGenerator.Emit(OpCodes.Shl);
        //}

        ///// <summary>
        ///// Pops two values from the stack, shifts the first to the right, then pushes the result
        ///// to the stack.  The sign bit is preserved.
        ///// </summary>
        //public void emitShiftRight() {
        //    currentGenerator.Emit(OpCodes.Shr);
        //}

        ///// <summary>
        ///// Pops two values from the stack, shifts the first to the right, then pushes the result
        ///// to the stack.  The sign bit is not preserved.
        ///// </summary>
        //public void emitShiftRightUnsigned() {
        //    currentGenerator.Emit(OpCodes.Shr_Un);
        //}



        ////     CONVERSIONS
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Pops a value from the stack, converts it to an object reference, then pushes it back onto
        ///// the stack.
        ///// </summary>
        //public void emitBox(Type type) {
        //    if (type == null)
        //        throw new ArgumentNullException("type");
        //    if (type.IsValueType == false)
        //        throw new ArgumentException("The type to box must be a value type.", "type");
        //    currentGenerator.Emit(OpCodes.Box, type);
        //}

        ///// <summary>
        ///// Pops an object reference (representing a boxed value) from the stack, extracts the
        ///// address, then pushes that address onto the stack.
        ///// </summary>
        ///// <param name="type"> The type of the boxed value.  This should be a value type. </param>
        //public void emitUnbox(Type type) {
        //    if (type == null)
        //        throw new ArgumentNullException("type");
        //    if (type.IsValueType == false)
        //        throw new ArgumentException("The type of the boxed value must be a value type.", "type");
        //    currentGenerator.Emit(OpCodes.Unbox, type);
        //}

        ///// <summary>
        ///// Pops an object reference (representing a boxed value) from the stack, extracts the value,
        ///// then pushes the value onto the stack.
        ///// </summary>
        ///// <param name="type"> The type of the boxed value.  This should be a value type. </param>
        //public void emitUnboxAny(Type type) {
        //    if (type == null)
        //        throw new ArgumentNullException("type");
        //    if (type.IsValueType == false)
        //        throw new ArgumentException("The type of the boxed value must be a value type.", "type");
        //    currentGenerator.Emit(OpCodes.Unbox_Any, type);
        //}

        ///// <summary>
        ///// Pops a value from the stack, converts it to a signed integer, then pushes it back onto
        ///// the stack.
        ///// </summary>
        //public void emitConvertToInt32() {
        //    currentGenerator.Emit(OpCodes.Conv_I4);
        //}

        ///// <summary>
        ///// Pops a value from the stack, converts it to an unsigned integer, then pushes it back
        ///// onto the stack.
        ///// </summary>
        //public void emitConvertToUnsignedInteger() {
        //    currentGenerator.Emit(OpCodes.Conv_U4);
        //}

        ///// <summary>
        ///// Pops a value from the stack, converts it to a signed 64-bit integer, then pushes it
        ///// back onto the stack.
        ///// </summary>
        //public void emitConvertToInt64() {
        //    currentGenerator.Emit(OpCodes.Conv_I8);
        //}

        ///// <summary>
        ///// Pops a value from the stack, converts it to an unsigned 64-bit integer, then pushes it
        ///// back onto the stack.
        ///// </summary>
        //public void emitConvertToUnsignedInt64() {
        //    currentGenerator.Emit(OpCodes.Conv_U8);
        //}

        ///// <summary>
        ///// Pops a value from the stack, converts it to a double, then pushes it back onto
        ///// the stack.
        ///// </summary>
        //public void emitConvertToDouble() {
        //    currentGenerator.Emit(OpCodes.Conv_R8);
        //}

        ///// <summary>
        ///// Pops an unsigned integer from the stack, converts it to a double, then pushes it back onto
        ///// the stack.
        ///// </summary>
        //public void ConvertUnsignedToDouble() {
        //    currentGenerator.Emit(OpCodes.Conv_R_Un);
        //}



        ////     OBJECTS, METHODS, TYPES AND FIELDS
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Pops the constructor arguments off the stack and creates a new instance of the object.
        ///// </summary>
        ///// <param name="constructor"> The constructor that is used to initialize the object. </param>
        //public void emitNewObject(System.Reflection.ConstructorInfo constructor) {
        //    currentGenerator.Emit(OpCodes.Newobj, constructor);
        //}

        ///// <summary>
        ///// Pops the method arguments off the stack, calls the given method, then pushes the result
        ///// to the stack (if there was one).  This operation can be used to call instance methods,
        ///// but virtual overrides will not be called and a null check will not be performed at the
        ///// callsite.
        ///// </summary>
        ///// <param name="method"> The method to call. </param>
        //public void emitCallStatic(System.Reflection.MethodBase method) {
        //    if (method is System.Reflection.MethodInfo)
        //        currentGenerator.Emit(OpCodes.Call, (System.Reflection.MethodInfo)method);
        //    else if (method is System.Reflection.ConstructorInfo)
        //        currentGenerator.Emit(OpCodes.Call, (System.Reflection.ConstructorInfo)method);
        //    else
        //        throw new InvalidOperationException("Unsupported subtype of MethodBase.");
        //}

        ///// <summary>
        ///// Pops the method arguments off the stack, calls the given method, then pushes the result
        ///// to the stack (if there was one).  This operation cannot be used to call static methods.
        ///// Virtual overrides are obeyed and a null check is performed.
        ///// </summary>
        ///// <param name="method"> The method to call. </param>
        ///// <exception cref="ArgumentException"> The method is static. </exception>
        //public void emitCallVirtual(System.Reflection.MethodBase method) {
        //    if (method.IsStatic == true)
        //        throw new ArgumentException("Static methods cannot be called this method.", "method");
        //    if (method is System.Reflection.ConstructorInfo)
        //        currentGenerator.Emit(OpCodes.Callvirt, (System.Reflection.ConstructorInfo)method);
        //    else if (method is System.Reflection.MethodInfo)
        //        currentGenerator.Emit(OpCodes.Callvirt, (System.Reflection.MethodInfo)method);
        //    else
        //        throw new InvalidOperationException("Unsupported subtype of MethodBase.");
        //}

        ///// <summary>
        ///// Pushes the value of the given field onto the stack.
        ///// </summary>
        ///// <param name="field"> The field whose value will be pushed. </param>
        //public void emitLoadField(System.Reflection.FieldInfo field) {
        //    if (field.IsStatic)
        //        currentGenerator.Emit(OpCodes.Ldsfld, field);
        //    else
        //        currentGenerator.Emit(OpCodes.Ldfld, field);
        //}

        ///// <summary>
        ///// Pops a value off the stack and stores it in the given field.
        ///// </summary>
        ///// <param name="field"> The field to modify. </param>
        //public void emitStoreField(System.Reflection.FieldInfo field) {
        //    if (field.IsStatic)
        //        currentGenerator.Emit(OpCodes.Stsfld, field);
        //    else
        //        currentGenerator.Emit(OpCodes.Stfld, field);
        //}

        ///// <summary>
        ///// Pops a value off the stack and stores it in the given field.
        ///// </summary>
        ///// <param name="field"> The field to modify. </param>
        //public void emitStoreInstanceField(System.Reflection.FieldInfo field) {
        //    currentGenerator.Emit(OpCodes.Stfld, field);
        //}

        ///// <summary>
        ///// Pops an object off the stack, checks that the object inherits from or implements the
        ///// given type, and pushes the object onto the stack if the check was successful or
        ///// throws an InvalidCastException if the check failed.
        ///// </summary>
        ///// <param name="type"> The type of the class the object inherits from or the interface the
        ///// object implements. </param>
        //public void CastClass(Type type) {
        //    currentGenerator.Emit(OpCodes.Castclass, type);
        //}

        ///// <summary>
        ///// Pops an object off the stack, checks that the object inherits from or implements the
        ///// given type, and pushes either the object (if the check was successful) or <c>null</c>
        ///// (if the check failed) onto the stack.
        ///// </summary>
        ///// <param name="type"> The type of the class the object inherits from or the interface the
        ///// object implements. </param>
        //public void IsInstance(Type type) {
        //    currentGenerator.Emit(OpCodes.Isinst, type);
        //}

        ///// <summary>
        ///// Pushes a RuntimeTypeHandle corresponding to the given type onto the evaluation stack.
        ///// </summary>
        ///// <param name="type"> The type to convert to a RuntimeTypeHandle. </param>
        //public void loadToken(Type type) {
        //    currentGenerator.Emit(OpCodes.Ldtoken, type);
        //}

        ///// <summary>
        ///// Pushes a RuntimeMethodHandle corresponding to the given method onto the evaluation
        ///// stack.
        ///// </summary>
        ///// <param name="method"> The method to convert to a RuntimeMethodHandle. </param>
        //public void loadToken(System.Reflection.MethodBase method) {
        //    if (method is System.Reflection.ConstructorInfo)
        //        currentGenerator.Emit(OpCodes.Ldtoken, (System.Reflection.ConstructorInfo)method);
        //    else if (method is System.Reflection.MethodInfo)
        //        currentGenerator.Emit(OpCodes.Ldtoken, (System.Reflection.MethodInfo)method);
        //    else
        //        throw new InvalidOperationException("Unsupported subtype of MethodBase.");
        //}

        ///// <summary>
        ///// Pushes a RuntimeFieldHandle corresponding to the given field onto the evaluation stack.
        ///// </summary>
        ///// <param name="field"> The type to convert to a RuntimeFieldHandle. </param>
        //public void loadToken(System.Reflection.FieldInfo field) {
        //    currentGenerator.Emit(OpCodes.Ldtoken, field);
        //}

        ///// <summary>
        ///// Pushes a pointer to the native code implementing the given method onto the evaluation
        ///// stack.  The virtual qualifier will be ignored, if present.
        ///// </summary>
        ///// <param name="method"> The method to retrieve a pointer for. </param>
        //public void loadStaticMethodPointer(System.Reflection.MethodBase method) {
        //    if (method is System.Reflection.ConstructorInfo)
        //        currentGenerator.Emit(OpCodes.Ldftn, (System.Reflection.ConstructorInfo)method);
        //    else if (method is System.Reflection.MethodInfo)
        //        currentGenerator.Emit(OpCodes.Ldftn, (System.Reflection.MethodInfo)method);
        //    else
        //        throw new InvalidOperationException("Unsupported subtype of MethodBase.");
        //}

        ///// <summary>
        ///// Pushes a pointer to the native code implementing the given method onto the evaluation
        ///// stack.  This method cannot be used to retrieve a pointer to a static method.
        ///// </summary>
        ///// <param name="method"> The method to retrieve a pointer for. </param>
        ///// <exception cref="ArgumentException"> The method is static. </exception>
        //public void loadVirtualMethodPointer(System.Reflection.MethodBase method) {
        //    if (method != null && method.IsStatic == true)
        //        throw new ArgumentException("The given method cannot be static.", "method");
        //    if (method is System.Reflection.ConstructorInfo)
        //        currentGenerator.Emit(OpCodes.Ldvirtftn, (System.Reflection.ConstructorInfo)method);
        //    else if (method is System.Reflection.MethodInfo)
        //        currentGenerator.Emit(OpCodes.Ldvirtftn, (System.Reflection.MethodInfo)method);
        //    else
        //        throw new InvalidOperationException("Unsupported subtype of MethodBase.");
        //}

        ///// <summary>
        ///// Pops a managed or native pointer off the stack and initializes the referenced type with
        ///// zeros.
        ///// </summary>
        ///// <param name="type"> The type the pointer on the top of the stack is pointing to. </param>
        //public void InitObject(Type type) {
        //    if (type == null)
        //        throw new ArgumentNullException("type");
        //    currentGenerator.Emit(OpCodes.Initobj, type);
        //}



        ////     ARRAYS
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Pops the size of the array off the stack and pushes a new array of the given type onto
        ///// the stack.
        ///// </summary>
        ///// <param name="type"> The element type. </param>
        //public void NewArray(Type type) {
        //    currentGenerator.Emit(OpCodes.Newarr, type);
        //}

        ///// <summary>
        ///// Pops the array and index off the stack and pushes the element value onto the stack.
        ///// </summary>
        ///// <param name="type"> The element type. </param>
        //public void loadArrayElement(Type type) {
        //    switch (Type.GetTypeCode(type)) {
        //        case TypeCode.Byte:
        //        case TypeCode.SByte:
        //            currentGenerator.Emit(OpCodes.Ldelem_I1);
        //            break;
        //        case TypeCode.UInt16:
        //        case TypeCode.Int16:
        //            currentGenerator.Emit(OpCodes.Ldelem_I2);
        //            break;
        //        case TypeCode.UInt32:
        //        case TypeCode.Int32:
        //            currentGenerator.Emit(OpCodes.Ldelem_I4);
        //            break;
        //        case TypeCode.UInt64:
        //        case TypeCode.Int64:
        //            currentGenerator.Emit(OpCodes.Ldelem_I8);
        //            break;
        //        case TypeCode.Single:
        //            currentGenerator.Emit(OpCodes.Ldelem_R4);
        //            break;
        //        case TypeCode.Double:
        //            currentGenerator.Emit(OpCodes.Ldelem_R8);
        //            break;
        //        default:
        //            if (type.IsClass == true)
        //                currentGenerator.Emit(OpCodes.Ldelem_Ref);
        //            else
        //                currentGenerator.Emit(OpCodes.Ldelem, type);
        //            break;
        //    }
        //}

        ///// <summary>
        ///// Pops the array, index and value off the stack and stores the value in the array.
        ///// </summary>
        ///// <param name="type"> The element type. </param>
        //public void StoreArrayElement(Type type) {
        //    switch (Type.GetTypeCode(type)) {
        //        case TypeCode.Byte:
        //        case TypeCode.SByte:
        //            currentGenerator.Emit(OpCodes.Stelem_I1);
        //            break;
        //        case TypeCode.UInt16:
        //        case TypeCode.Int16:
        //            currentGenerator.Emit(OpCodes.Stelem_I2);
        //            break;
        //        case TypeCode.UInt32:
        //        case TypeCode.Int32:
        //            currentGenerator.Emit(OpCodes.Stelem_I4);
        //            break;
        //        case TypeCode.UInt64:
        //        case TypeCode.Int64:
        //            currentGenerator.Emit(OpCodes.Stelem_I8);
        //            break;
        //        case TypeCode.Single:
        //            currentGenerator.Emit(OpCodes.Stelem_R4);
        //            break;
        //        case TypeCode.Double:
        //            currentGenerator.Emit(OpCodes.Stelem_R8);
        //            break;
        //        default:
        //            if (type.IsClass == true)
        //                currentGenerator.Emit(OpCodes.Stelem_Ref);
        //            else
        //                currentGenerator.Emit(OpCodes.Stelem, type);
        //            break;
        //    }
        //}

        ///// <summary>
        ///// Pops an array off the stack and pushes the length of the array onto the stack.
        ///// </summary>
        //public void loadArrayLength() {
        //    currentGenerator.Emit(OpCodes.Ldlen);
        //}



        ////     EXCEPTION HANDLING
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Pops an exception object off the stack and throws the exception.
        ///// </summary>
        //public void emitThrow() {
        //    currentGenerator.Emit(OpCodes.Throw);
        //}

        ///// <summary>
        ///// Pops an exception object off the stack and throws the exception.
        ///// </summary>
        //public void emitRethrow() {
        //    currentGenerator.Emit(OpCodes.Rethrow);
        //}


        ///// <summary>
        ///// Begins a try-catch-finally block.  After issuing this instruction any following
        ///// instructions are conceptually within the try block.
        ///// </summary>
        //public void beginExceptionBlock() {
        //    currentGenerator.BeginExceptionBlock();
        //}

        ///// <summary>
        ///// Ends a try-catch-finally block.  BeginExceptionBlock() must have already been called.
        ///// </summary>
        //public void endExceptionBlock() {
        //    currentGenerator.EndExceptionBlock();
        //}

        ///// <summary>
        ///// Begins a catch block.  BeginExceptionBlock() must have already been called.
        ///// </summary>
        ///// <param name="exceptionType"> The type of exception to handle. </param>
        //public void beginCatchBlock(Type exceptionType) {
        //    currentGenerator.BeginCatchBlock(exceptionType);
        //}

        ///// <summary>
        ///// Begins a finally block.  BeginExceptionBlock() must have already been called.
        ///// </summary>
        //public void beginFinallyBlock() {
        //    currentGenerator.BeginFinallyBlock();
        //}

        ///// <summary>
        ///// Begins a filter block.  BeginExceptionBlock() must have already been called.
        ///// </summary>
        //public void beginFilterBlock() {
        //    currentGenerator.BeginExceptFilterBlock();
        //}

        ///// <summary>
        ///// Begins a fault block.  BeginExceptionBlock() must have already been called.
        ///// </summary>
        //public void beginFaultBlock() {
        //    currentGenerator.BeginFaultBlock();
        //}

        ///// <summary>
        ///// Unconditionally branches to the given label.  Unlike the regular branch instruction,
        ///// this instruction can exit out of try, filter and catch blocks.
        ///// </summary>
        ///// <param name="label"> The label to branch to. </param>
        //public void emitLeave(Label label) {


        //    currentGenerator.Emit(OpCodes.Leave, label);
        //}

        ///// <summary>
        ///// This instruction can be used from within a finally block to resume the exception
        ///// handling process.  It is the only valid way of leaving a finally block.
        ///// </summary>
        //public void endFinally() {
        //    currentGenerator.Emit(OpCodes.Endfinally);
        //}

        ///// <summary>
        ///// This instruction can be used from within a filter block to indicate whether the
        ///// exception will be handled.  It pops an integer from the stack which should be <c>0</c>
        ///// to continue searching for an exception handler or <c>1</c> to use the handler
        ///// associated with the filter.  EndFilter() must be called at the end of a filter block.
        ///// </summary>
        //public void endFilter() {
        //    currentGenerator.Emit(OpCodes.Endfilter);
        //}



        ////     DEBUGGING SUPPORT
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Triggers a breakpoint in an attached debugger.
        ///// </summary>
        //public void Breakpoint() {
        //    currentGenerator.Emit(OpCodes.Break);
        //}

        ///// <summary>
        ///// Marks a sequence point in the Microsoft intermediate language (MSIL) stream.
        ///// </summary>
        ///// <param name="document"> The document for which the sequence point is being defined. </param>
        ///// <param name="startLine"> The line where the sequence point begins. </param>
        ///// <param name="startColumn"> The column in the line where the sequence point begins. </param>
        ///// <param name="endLine"> The line where the sequence point ends. </param>
        ///// <param name="endColumn"> The column in the line where the sequence point ends. </param>
        //public void markSequencePoint(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) {
        //    currentGenerator.MarkSequencePoint(document, startLine, startColumn, endLine, endColumn);
        //}



        ////     MISC
        ////_________________________________________________________________________________________

        ///// <summary>
        ///// Does nothing.
        ///// </summary>
        //public void emitNoOperation() {
        //    currentGenerator.Emit(OpCodes.Nop);
        //}


        //#endregion


        //public void markLocation(Node node) {

        //}

        ///// <summary>
        ///// 控制调试器移动到指定的位置。
        ///// </summary>
        ///// <param name="startLocation"></param>
        ///// <param name="endLocation"></param>
        //public void markLocation(Location startLocation, Location endLocation) {

        //}

        //public bool needToCheckOverflow(TypeReference typeReference) {
        //    return checkOverflow && typeReference != PredefinedTypes.@float && typeReference != PredefinedTypes.@double;
        //}
    }

}